package com.ryan.ohos.extension.util;

import ohos.agp.components.*;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.bundle.AbilityInfo;

import java.util.HashMap;
import java.util.List;

public abstract class EasyGridProvider<T> extends BaseItemProvider {
    //默认的布局类型
    public static final int ITEM_DEFAULT_TYPE = 0;
    //空布局
    public static final int ITEM_EMPTY_TYPE = -1;
    protected Context mContext;
    private List<T> data;
    protected int numColumns = 1;
    protected int gridSpacing = 0;
    private int displayWidth;
    private OnItemClickListener onItemClickListener;


    public EasyGridProvider(Context mContext) {
        this(mContext, null);
    }

    private int getDisplayWidthInPx(Context context) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        Point point = new Point();
        display.getSize(point);
        return (int) point.getPointX();
    }

    /**
     * @param context 上下文
     * @param data    数据源
     */
    public EasyGridProvider(Context context, List<T> data) {
        this.mContext = context;
        this.data = data;
        this.displayWidth = getDisplayWidthInPx(context);
    }

    public void updateDisplayWidth(AbilityInfo.DisplayOrientation displayOrientation) {
        this.displayWidth = getDisplayWidthInPx(mContext);
    }

    public void setNumColumns(int numColumns) {
        this.numColumns = numColumns;
    }

    public void setGridSpacing(float gridSpacing) {
        this.gridSpacing = (int) (gridSpacing / 2);
    }

    public void setData(List<T> data) {
        this.data = data;
        notifyDataChanged();
    }

    public List<T> getData() {
        return data;
    }

    public int getDataCount() {
        return data != null ? data.size() : 0;
    }

    public int getListPosition(int position) {

        return position / numColumns;
    }


    @Override
    public int getCount() {
        if (data != null) {
            return data.size() % numColumns == 0 ? data.size() / numColumns : data.size() / numColumns + 1;
        } else {
            return 0;
        }
    }

    @Override
    public T getItem(int position) {
        if (data != null) {
            return data.get(position);
        } else {
            return null;
        }
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemComponentType(int position) {
        if (position >= getDataCount()) {
            return ITEM_EMPTY_TYPE;
        }
        return ITEM_DEFAULT_TYPE;
    }


    @Override
    public Component getComponent(int position, Component convertComponent, ComponentContainer parent) {
        if (convertComponent == null) {
            convertComponent = new DirectionalLayout(mContext);
            ((DirectionalLayout) convertComponent).setOrientation(Component.HORIZONTAL);
            ComponentContainer.LayoutConfig layoutConfig = convertComponent.getLayoutConfig();
            layoutConfig.width = DependentLayout.LayoutConfig.MATCH_PARENT;
            layoutConfig.height = DependentLayout.LayoutConfig.MATCH_CONTENT;
            convertComponent.setLayoutConfig(layoutConfig);
        }

        DirectionalLayout convertDirectionalLayout = (DirectionalLayout) convertComponent;

        for (int i = 0; i < numColumns; i++) {

            int itemPosition = position * numColumns + i;

            int itemComponentType = getItemComponentType(itemPosition);

            Component childConvertComponent = convertDirectionalLayout.getComponentAt(i);
            ViewHolder viewHolder = null;
            if (childConvertComponent == null) {

                childConvertComponent = LayoutScatter.getInstance(mContext).parse(getLayoutId(),
                        null, false);
                viewHolder = new ViewHolder(childConvertComponent, itemComponentType);
                childConvertComponent.setTag(viewHolder);
                convertDirectionalLayout.addComponent(childConvertComponent);
                int height = (displayWidth - numColumns * gridSpacing) / numColumns;
                ComponentContainer.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(0,
                        height, LayoutAlignment.TOP, 1);
                childConvertComponent.setLayoutConfig(layoutConfig);
                if (gridSpacing != 0) {
                    if ((itemPosition + 1) % numColumns == 0) {
                        childConvertComponent.setMarginsLeftAndRight(gridSpacing, 0);
                    } else if ((itemPosition) % numColumns == 0) {
                        childConvertComponent.setMarginsLeftAndRight(0, gridSpacing);
                    } else {
                        childConvertComponent.setMarginsLeftAndRight(gridSpacing, gridSpacing);
                    }
                    childConvertComponent.setMarginsTopAndBottom(gridSpacing, gridSpacing);
                }
            } else {
                viewHolder = (ViewHolder) childConvertComponent.getTag();
            }

            Component itemView = viewHolder.getItemView();

            viewHolder.setAdapterPosition(itemPosition);
            if (itemComponentType == ITEM_DEFAULT_TYPE) {
                itemView.setClickedListener(component1 -> {
                    if (onItemClickListener != null) {
                        onItemClickListener.onItemClick(component1, itemPosition);
                    }
                });
                bind(viewHolder, getItem(itemPosition), itemPosition);
            } else {
                itemView.setClickedListener(null);
                bindPlaceholder(viewHolder, itemPosition);
            }
        }
        return convertComponent;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    protected abstract void bind(ViewHolder holder, T item, int position);

    protected abstract void bindPlaceholder(ViewHolder holder, int position);

    protected abstract int getLayoutId();

    public static class ViewHolder {
        private HashMap<Integer, Component> mViews = new HashMap<>();
        private Component itemView;
        private int adapterPosition;
        private int componentType;

        ViewHolder(Component component) {
            this(component, ITEM_DEFAULT_TYPE);
        }

        ViewHolder(Component component, int componentType) {
            this.itemView = component;
            this.componentType = componentType;
        }

        public void setAdapterPosition(int adapterPosition) {
            this.adapterPosition = adapterPosition;
        }

        public int getAdapterPosition() {
            return adapterPosition;
        }

        public Component getItemView() {
            return itemView;
        }

        public ViewHolder setText(int viewId, String text) {
            ((Text) getView(viewId)).setText(text);
            return this;
        }

        public <E extends Component> E getView(int viewId) {
            return (E) mViews.computeIfAbsent(viewId, id -> itemView.findComponentById(id));
        }

    }

    public static abstract class OnItemClickListener {
        public abstract void onItemClick(Component component, int position);
    }
}
